/*
 * Copyright 2016. chenshufei
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package sz.szsmk.citizencard.smkretrofit;

import com.squareup.okhttp.Headers;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.ResponseBody;

import java.io.IOException;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.logging.HttpLoggingInterceptor;
import okio.Buffer;
import okio.BufferedSource;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;
import sz.szsmk.citizencard.log.L;
import sz.szsmk.citizencard.model.network.bean.request.AdvertisementsReq;
import sz.szsmk.citizencard.model.network.bean.request.IBaseRequest;
import sz.szsmk.citizencard.model.network.bean.request.PreAuthNewReq;
import sz.szsmk.citizencard.model.network.bean.request.SuEXingReq;
import sz.szsmk.citizencard.model.network.bean.request.UserBehaviorBrowseReq;
import sz.szsmk.citizencard.model.network.bean.request.UserBehaviorReq;
import sz.szsmk.citizencard.model.network.bean.request.VerifyBindNgUserReq;
import sz.szsmk.citizencard.model.network.bean.response.AdvertisementsRes;
import sz.szsmk.citizencard.model.network.bean.response.BaseBean;
import sz.szsmk.citizencard.model.network.bean.response.CheckBankCodeRes;
import sz.szsmk.citizencard.model.network.bean.response.CheckIsChargeRes;
import sz.szsmk.citizencard.model.network.bean.response.GetCodeResponse;
import sz.szsmk.citizencard.model.network.bean.response.OauthTokenRes;
import sz.szsmk.citizencard.model.network.bean.response.VerifyBindNgUserRes;
import sz.szsmk.citizencard.model.network.clarkbean.response.AreaInfoResponse;
import sz.szsmk.citizencard.model.network.dzbean.req.BaseRequest;
import sz.szsmk.citizencard.model.network.dzbean.req.BillRequest;
import sz.szsmk.citizencard.model.network.dzbean.req.ChangeBankCardRequest;
import sz.szsmk.citizencard.model.network.dzbean.req.CheckBankCardRequset;
import sz.szsmk.citizencard.model.network.dzbean.req.CheckPwdRequest;
import sz.szsmk.citizencard.model.network.dzbean.req.CommonRequest;
import sz.szsmk.citizencard.model.network.dzbean.req.GetBankNameRequest;
import sz.szsmk.citizencard.model.network.dzbean.req.GetCheckCodeCcbReq;
import sz.szsmk.citizencard.model.network.dzbean.req.GetCheckCodeRequest;
import sz.szsmk.citizencard.model.network.dzbean.req.GetOpenIdReq;
import sz.szsmk.citizencard.model.network.dzbean.req.ModifyPwdRequest;
import sz.szsmk.citizencard.model.network.dzbean.req.MoneyRequest;
import sz.szsmk.citizencard.model.network.dzbean.req.OldUserCheckRequest;
import sz.szsmk.citizencard.model.network.dzbean.req.PreAuthRequest;
import sz.szsmk.citizencard.model.network.dzbean.req.PreAuthThiedReq;
import sz.szsmk.citizencard.model.network.dzbean.req.PreAuthThirdRes;
import sz.szsmk.citizencard.model.network.dzbean.req.QrCodeNumberRequest;
import sz.szsmk.citizencard.model.network.dzbean.req.RealNameAuthenticationRequest;
import sz.szsmk.citizencard.model.network.dzbean.req.SetPayPwdRequest;
import sz.szsmk.citizencard.model.network.dzbean.req.UserInfoUpdateRequest;
import sz.szsmk.citizencard.model.network.dzbean.res.BillResponse;
import sz.szsmk.citizencard.model.network.dzbean.res.CheckIsRealName2Res;
import sz.szsmk.citizencard.model.network.dzbean.res.CheckIsRealNameRes;
import sz.szsmk.citizencard.model.network.dzbean.res.CheckPsdRes;
import sz.szsmk.citizencard.model.network.dzbean.res.FaqResponse;
import sz.szsmk.citizencard.model.network.dzbean.res.GetBalanceResponse;
import sz.szsmk.citizencard.model.network.dzbean.res.GetBankNameRes;
import sz.szsmk.citizencard.model.network.dzbean.res.GetJobRes;
import sz.szsmk.citizencard.model.network.dzbean.res.GetMyBankResponse;
import sz.szsmk.citizencard.model.network.dzbean.res.GetOpenIdRes;
import sz.szsmk.citizencard.model.network.dzbean.res.GetPeopleRes;
import sz.szsmk.citizencard.model.network.dzbean.res.GetUserInfoRes;
import sz.szsmk.citizencard.model.network.dzbean.res.OldCardRes;
import sz.szsmk.citizencard.model.network.dzbean.res.PreAuthRes;
import sz.szsmk.citizencard.model.network.dzbean.res.QrNumberResponse;
import sz.szsmk.citizencard.model.network.dzbean.res.RealNameResponse;
import sz.szsmk.citizencard.model.network.dzbean.res.SupportBankResponse;
import sz.szsmk.citizencard.model.network.dzbean.res.SysResponse;
import sz.szsmk.citizencard.retrofitrxjava.HttpApi;
import sz.szsmk.citizencard.retrofitrxjava.net.persistentcookiejar.PersistentCookieJar;
import sz.szsmk.citizencard.retrofitrxjava.newversion.HttpDateSource;
import sz.szsmk.citizencard.util.Constant;
import sz.szsmk.citizencard.util.CookieHandler;

/**
 * <br /> author: chenshufei
 * <br /> date: 16/1/5
 * <br /> email: chenshufei2@sina.com
 */
public class NetworkDateSource {
    private final HttpApi mHttpApi;
    private static PersistentCookieJar persistentCookieJar;
    private static final Charset UTF8 = Charset.forName("UTF-8");
    private static final NetworkDateSource sNetworkDateSource = new NetworkDateSource();

    static class Creator {

        public static HttpApi newHttpApi() {

            com.squareup.okhttp.OkHttpClient client = new com.squareup.okhttp.OkHttpClient();
            client.setConnectTimeout(20, TimeUnit.SECONDS);
            client.setReadTimeout(1000 * 120, TimeUnit.MILLISECONDS);
            client.setWriteTimeout(1000 * 120, TimeUnit.MILLISECONDS);
            CookieManager cookieManager = new CookieManager();
            cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
            client.setCookieHandler(cookieManager);
            HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            client.interceptors().add(new com.squareup.okhttp.Interceptor() {
                @Override
                public com.squareup.okhttp.Response intercept(Chain chain) throws IOException {
                    com.squareup.okhttp.Request request = chain.request();
                    com.squareup.okhttp.Request newRequest = request.newBuilder()
                            //.addHeader("accept", "application/json")
                            .addHeader("Content-Language", "zh-CN")
                            .addHeader("Accept-Language", "zh-CN")
                            .build();
                    Headers headers = request.headers();


//                    L.e("request url:" + request.toString());
//                    L.e("request headers:" + headers);
                    Map<String, List<String>> headerListMap = headers.toMultimap();
                    for (Map.Entry<String, List<String>> entry : headerListMap.entrySet()) {
                        List<String> values = entry.getValue();
                        StringBuffer sb = new StringBuffer();
                        for (String value : values) {
                            sb.append(value).append(" ");
                        }
                        L.e("   " + entry.getKey() + "=" + sb.toString());
                    }
//                    L.e("request body:" + request.body());


                    com.squareup.okhttp.Response proceed = chain.proceed(newRequest);
                    ResponseBody responseBody = proceed.body();
                    BufferedSource source = responseBody.source();
                    source.request(Long.MAX_VALUE); // Buffer the entire body.
                    Buffer buffer = source.buffer();

                    Charset charset = UTF8;
                    MediaType contentType = responseBody.contentType();
                    if (contentType != null) {
                        charset = contentType.charset(UTF8);
                    }

                    if (responseBody.contentLength() != 0) {
                        //logger.log("");
                        //logger.log(buffer.clone().readString(charset));
//                        L.e(Constant.TAG);
                        L.e(Constant.TAG,"request url:" + request.toString()+"dzsmk-----响应内容:" + buffer.clone().readString(charset));
                    }
                    String host = request.url().getHost();
                    CookieHandler.processResponseCookie(proceed, host);
                    return proceed;
                }
            });
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(Constant.DZ_BASE_URL)
                    .addConverterFactory(retrofit2.converter.gson.GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .client(HttpDateSource.INSTANCE.getOkHttpClient())
                    .build();
            return retrofit.create(HttpApi.class);
        }


    }


    private NetworkDateSource() {
        mHttpApi = NetworkDateSource.Creator.newHttpApi();

    }

    public static NetworkDateSource getInstance() {
        return sNetworkDateSource;
    }


    public HttpApi getHttpApi() {
        return mHttpApi;
    }

    // 不强制 T extends BaseBean 了
    private <T> Subscription doSubscription(Observable<T> observable, Action1<T> action1, Action1<Throwable> onError) {
        if (null != onError) {
            return observable.observeOn(AndroidSchedulers.mainThread()) //处理的结果 给 订阅者返回是在主线程的
                    .subscribeOn(Schedulers.io()) //被观察者observable是在io线程里处理的，
                    .subscribe(action1, onError);
        } else {
            return observable.observeOn(AndroidSchedulers.mainThread())
                    .subscribeOn(Schedulers.io())
                    .subscribe(action1);
        }
    }


    public Subscription preAuth(PreAuthRequest loginRequest, Action1<PreAuthRes> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.preAuth(loginRequest), action1, onError);
    }

    public Subscription preAuthThird(PreAuthThiedReq preAuthThiedReq, Action1<PreAuthThirdRes> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.preAuthThird(preAuthThiedReq), action1, onError);
    }


    public Subscription preAuthNew(PreAuthNewReq noticeDetailReq, Action1<BaseBean> action1, Action1<Throwable> onError) {
        return doSubscription(mHttpApi.preAuthNew(noticeDetailReq), action1, onError);
    }


    public Subscription sysConfig(CommonRequest loginRequest, Action1<SysResponse> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.sysConfig(loginRequest), action1, onError);
    }

    public Subscription getUserInfo(CommonRequest loginRequest, Action1<GetUserInfoRes> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.getUserInfo(loginRequest), action1, onError);
    }

    public Subscription getBillList(BillRequest billRequest, Action1<BillResponse> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.getBillList(billRequest), action1, onError);
    }

    public Subscription getBalance(CommonRequest billRequest, Action1<GetBalanceResponse> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.getBalance(billRequest), action1, onError);
    }

    public Subscription getOpenId(GetOpenIdReq getOpenIdReq, Action1<GetOpenIdRes> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.getOpenId(getOpenIdReq), action1, onError);
    }

    public Subscription getSupportBankList(CommonRequest billRequest, Action1<SupportBankResponse> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.getSupportBankList(billRequest), action1, onError);
    }

    public Subscription getBankName(GetBankNameRequest billRequest, Action1<GetBankNameRes> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.getBankName(billRequest), action1, onError);
    }

    public Subscription checkPwdSetting(CommonRequest billRequest, Action1<CheckPsdRes> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.checkPwdSetting(billRequest), action1, onError);
    }

    public Subscription getCheckCode(GetCheckCodeRequest getCheckCodeRequest, Action1<sz.szsmk.citizencard.model.network.dzbean.res.BaseRes> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.getCheckCode(getCheckCodeRequest), action1, onError);
    }

    public Subscription getCcbSmsCode(GetCheckCodeCcbReq getCheckCodeCcbReq, Action1<sz.szsmk.citizencard.model.network.dzbean.res.BaseRes> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.getCcbSmsCode(getCheckCodeCcbReq), action1, onError);
    }

    public Subscription realName(RealNameAuthenticationRequest realNameAuthenticationRequest, Action1<RealNameResponse> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.realName(realNameAuthenticationRequest), action1, onError);
    }

    public Subscription changeMyBankCard(ChangeBankCardRequest realNameAuthenticationRequest, Action1<RealNameResponse> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.changeMyBankCard(realNameAuthenticationRequest), action1, onError);
    }

    public Subscription oldUserCheck(OldUserCheckRequest oldUserCheckRequest, Action1<OldCardRes> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.oldUserCheck(oldUserCheckRequest), action1, onError);
    }

    public Subscription getPeople(CommonRequest realNameAuthenticationRequest, Action1<GetPeopleRes> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.getPeople(realNameAuthenticationRequest), action1, onError);
    }

    public Subscription getJob(CommonRequest realNameAuthenticationRequest, Action1<GetJobRes> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.getJob(realNameAuthenticationRequest), action1, onError);
    }

    public Subscription checkIsCharge(CommonRequest realNameAuthenticationRequest, Action1<CheckIsChargeRes> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.checkIsCharge(realNameAuthenticationRequest), action1, onError);
    }


    public Subscription setPayPassword(SetPayPwdRequest setPayPwdRequest, Action1<GetCodeResponse> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.setPayPassword(setPayPwdRequest), action1, onError);
    }

    public Subscription getMyCitizenCard(CommonRequest commonRequest, Action1<GetCodeResponse> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.getMyCitizenCard(commonRequest), action1, onError);
    }

    public Subscription updatePayPassword(ModifyPwdRequest setPayPwdRequest, Action1<GetCodeResponse> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.updatePayPassword(setPayPwdRequest), action1, onError);
    }

    public Subscription getQrNumber(QrCodeNumberRequest setPayPwdRequest, Action1<QrNumberResponse> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.getQrNumber(setPayPwdRequest), action1, onError);
    }

    public Subscription getMyBanks(CommonRequest commonRequest, Action1<GetMyBankResponse> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.getMyBanks(commonRequest), action1, onError);
    }

    public Subscription checkPayPassword(CheckPwdRequest commonRequest, Action1<GetMyBankResponse> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.checkPayPassword(commonRequest), action1, onError);
    }

    public Subscription recharge(MoneyRequest commonRequest, Action1<GetCodeResponse> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.recharge(commonRequest), action1, onError);
    }

    public Subscription getQa(CommonRequest commonRequest, Action1<FaqResponse> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.getQa(commonRequest), action1, onError);
    }

    public Subscription updateUserInfo(UserInfoUpdateRequest commonRequest, Action1<GetCodeResponse> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.updateUserInfo(commonRequest), action1, onError);
    }

    public Subscription checkIsRealName(CommonRequest commonRequest, Action1<CheckIsRealNameRes> action1, Action1<Throwable> onError) {
        return doSubscription(mHttpApi.checkIsRealName(commonRequest), action1, onError);
    }

    public Subscription checkIsRealName2(CommonRequest commonRequest, Action1<CheckIsRealName2Res> action1, Action1<Throwable> onError) {
        return doSubscription(mHttpApi.checkIsRealName2(commonRequest), action1, onError);
    }

    //苏e行 请求 判断密码
    public Subscription checkPwdForSeX(SuEXingReq suEXingReq, Action1<BaseBean> action1, Action1<Throwable> onError) {
        return doSubscription(mHttpApi.echeckPayPassWord(suEXingReq), action1, onError);
    }

    //请求电子市民卡 广告
    public Subscription getAdvertisements(AdvertisementsReq advertisementsReq, Action1<AdvertisementsRes> action1, Action1<Throwable> onError) {
        return doSubscription(mHttpApi.getAdvertisements(advertisementsReq), action1, onError);
    }

    public Subscription checkBankNoValidation(CheckBankCardRequset billRequest, Action1<CheckBankCodeRes> action1, Action1<Throwable> onError) {

        return doSubscription(mHttpApi.checkBankNoValidation(billRequest), action1, onError);
    }
    //统计点击
    public Subscription userBehaviorBrowse(UserBehaviorBrowseReq userBehaviorBrowseReq, Action1<BaseBean> action1, Action1<Throwable> onError) {
        return doSubscription(mHttpApi.userBehaviorBrowse(userBehaviorBrowseReq), action1, onError);
    }

    //活跃用户
    public Subscription userBehaviorActive(UserBehaviorReq queryUserCardRequest, Action1<BaseBean> action1, Action1<Throwable> onError) {
        return doSubscription(mHttpApi.userBehaviorActive(queryUserCardRequest), action1, onError);
    }


    public Subscription getAreaInfo(IBaseRequest baseRequest, Action1<AreaInfoResponse> action1, Action1<Throwable> onError){
        return doSubscription(mHttpApi.getAreaInfo(baseRequest), action1, onError);
    }


}
